package com.luojiang.validator.handler;

import com.luojiang.validator.util.JSONResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.UnexpectedTypeException;
import java.util.Set;

@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    /**
     * 校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(UnexpectedTypeException.class)
    @ResponseBody
    public JSONResult validationException(UnexpectedTypeException e) {
        logger.error("参数校验异常:", e);
        return JSONResult.failure(e.getMessage());
    }

    /**
     * Hibernate Validator参数校验异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public JSONResult handler(MethodArgumentNotValidException e) {
        BindingResult bindingResult = e.getBindingResult();
        ObjectError objectError = bindingResult.getAllErrors().get(0);
        return JSONResult.failure(-1, objectError.getDefaultMessage());
    }
    /**
     * 未被关注的异常信息，统一返回给客户端为“系统异常”
     *
     * @param e
     * @param response
     * @param request
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public JSONResult exceptionHandler(Exception e, HttpServletResponse response, HttpServletRequest request) {
        return JSONResult.failure(-1, "系统异常");
    }

    @ExceptionHandler(value = {MethodArgumentTypeMismatchException.class, MissingServletRequestParameterException.class, BindException.class, HttpMessageNotReadableException.class})
    public JSONResult handler(Exception e) {
        logger.error("参数异常:", e);
        return JSONResult.failure(-5, e.getMessage());
    }

    /**
     * Spring Validator参数校验异常处理
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public JSONResult handler(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
        for (ConstraintViolation<?> constraintViolation : constraintViolations) {
            String message = constraintViolation.getMessage();
            if (!StringUtils.isEmpty(message)) {
                //直接返回第一个错误信息
                return JSONResult.failure(-5, message);
            }
        }
        return JSONResult.failure(-6, null);
    }

}